<?php

namespace web\api\controller;

class ApiBase extends \web\common\controller\Controller {

    /**
     * 获取提交的参数数据
     * @var type 
     */
    private $paramData = null;

    /**
     * 提交的签名值
     * @var type 
     */
    private $signValue = '';

    /**
     * 加密key
     * @var type 
     */
    protected $apikey = '571A7DC545713FC6417547D0B3D1AC25';
    protected $sign_passtime = 60;

    /**
     * 接口域名地址
     * @var type 
     */
    protected $api_url = '';

    /**
     * 全局redis缓存
     * @var type 
     */
    protected $globalCache = null; //think\cache\driver\Redis
    
    /**
     * 数据缓存
     * @var type 
     */
    protected $dataCache = null;
    protected $base_url = 'http://www.papa-video.com';
//    protected $ws_base_url = 'http://douxin.w3.tuuz.ltd:1700/';

    
    protected function _initialize() {
        header("Access-Control-Allow-Origin:*");
        $this->bindCache($this->request); //绑定缓存实例
        $this->globalCache = $this->request->__get('global_cache'); //实例化
        $this->dataCache = $this->request->__get('data_cache');
        if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
            return true;
        }
        $this->request->filter('trim,strip_tags,htmlspecialchars');
		
        //签名验证
        if(!empty($_POST)){
            $this->signValue = $_POST['sign']; //取出签名
            $this->paramData = $this->getPostData();
            $this->checkSign();
        }else if(!empty($_GET)){
            $this->signValue = $_GET['sign']; //取出签名
            $this->paramData = $this->getRequestData();
            $this->checkSign();
        }
		//$this->checkVersion();

    }

    public function getSysCache(){
        $arr = $this->globalCache->get('sys_version');
        if(!$arr){
            $sysM = new \web\common\model\sys\SysParameterModel();
            $map['field_name'] = ['in',['sys_version','app_download_url','is_forced_updates','app_switch']] ;
            $link = $sysM->field('field_name,parameter_val')->where($map)->select();
            $arr = [];
            foreach ($link as $k => $v) {
                $arr[$v['field_name']] = $v['parameter_val'];
            }
            $this->globalCache->set('sys_version',$arr);
        }
        return $arr;
    }

     /**
     *  版本验证
     */
    public function checkVersion(){
        $arr = $this->getSysCache();
        if(!isset($arr['app_switch'])){
            return $this->failJSON(lang('API_VERSION'));
        }
        if(!$arr['app_switch']){
            return $this->failJSON(lang('API_VERSION'));
        }
        if(!isset($this->paramData['version'])){
            return $this->failLoginJSON($arr['app_download_url'],403);
        }
        if($this->paramData['version']!=$arr['sys_version']&&$arr['is_forced_updates']){
            return $this->failLoginJSON($arr['app_download_url'],403);
        }
    }

    /**
     * 设置当前请求绑定的缓存对象实例--redis
     * @param type $request
     */
    private function bindCache(&$request) {
        if (!$request->__isset('data_cache')) {
            $dataCache = \think\Cache::connect(\think\Config::get('data_cache'));
            $request->bind('data_cache', $dataCache);
        }
        if (!$request->__isset('global_cache')) {
            $globalCache = \think\Cache::connect(\think\Config::get('global_cache'));
            $request->bind('global_cache', $globalCache);
        }
    }
    
    /**
     * 获取系统配置信息。
     * @return type
     */
    public function getSysConfig() {
        $m = new \web\common\model\sys\SysOemModel();
        return $m->getSysConfig(1);
    }

    /**
     * 获取全局缓存数据
     * @param type $key
     * @return type
     */
    protected function getGlobalCache($key = null) {
        $data = null;
        if ($this->globalCache) {
            if (empty($key)) {
                return $this->failJSON(lang("API_LOGIN_FAIL"));
            }
            $data = $this->globalCache->get($key);
        }
        return $data;
    }

    /**
     * 设置全局缓存数据
     * @param type $data
     * @param type $key
     * @param type $expire
     */
    protected function setGlobalCache($data, $key = null, $expire = null) {
        if ($this->globalCache) {
            if (empty($key))
                $key = $this->getCacheKey();
            return $this->globalCache->set($key, $data, $expire);
        }
    }

    /**
     *
     * 检测签名
     */
    protected function checkSign() {
		return true;
		
        if(!isset($this->paramData['t'])){
            $this->failJSON(lang('API_WRONG_SIGN'));
        }
        if((time()-$this->paramData['t'])>$this->sign_passtime){
            $this->failJSON(lang('API_TIMEOUT'));
        }
        $sign = $this->makeSign();
        if ($this->signValue === $sign) {
            return true;
        } else {
            $this->failJSON(lang('API_WRONG_SIGN'));
        }
    }

    /**
     * 生成签名
     */
    private function makeSign() {
        return strtoupper(md5($this->paramData['t'].$this->apikey));
    }

    /**
     * 格式化参数格式化成url参数(字典排序后重组)
     */
    private function toUrlParams() {
        $buff = '';
        foreach ($this->paramData as $k => $v) {
            if ($v != '' && !is_array($v)) {
                if (preg_match('/[\x80-\xff]./', $v))
                    $buff .= $k . '=' . urldecode($v) . '&';
                else
                    $buff .= $k . '=' . $v . '&';
            }
        }
        $buff = trim($buff, '&');
        return $buff;
    }

    /**
     * 获取参数值.
     * @param type $name
     * @param type $no_null 不能为空
     * @return type
     */
    protected function getParamVal($name, $no_null = true, $type = '') {
        $data = $this->paramData[$name];
		//return $this->paramData;
        if ($no_null && $data == null) {
            $this->failJSON(lang('API_PARAM'). $name . '！');
        } else {
            if ($data != null) {
                if ($type == 'int') {
                    if (!is_numeric($data))
                        $this->failJSON('参数' . $name . '类型有误!');
                    else
                        $data = intval($data);
                } else if ($type == 'float') {
                    if (!is_numeric($data))
                        $this->failJSON('参数' . $name . '类型有误！');
                    else
                        $data = floatval($data);
                } else if ($type == 'double') {
                    if (!is_numeric($data))
                        $this->failJSON('参数' . $name . '类型有误！');
                    else
                        $data = doubleval($data);
                }
            }
            $this->paramData[$name] = $data;
            return $data;
        }
    }

    /**
     * 获取提交过来的参数数据 (数组)       
     * @return type
     */
    private function getRequestData() {
        $data = $_GET;
        // unset($data['token']);
        unset($data['sign']);
        $data['api_key'] = $this->apikey;
        return $data;
    }

    /**
     * 获取POST提交的数据。
     * @return type
     */
    protected function getPostData() {
        $data = array();
        if (isset($_POST)) {
            $post_data = $_POST;
            $data = !empty($post_data) ? $post_data : array();
            unset($data['sign']);
            $data['api_key'] = $this->apikey;
        } else {
            return $this->failJSON('post data is empty');
        }
        return $data;
    }

    /**
     * 输出错误JSON信息。
     * @param type $message     
     */
    protected function failJSON($message) {
        $message = lang($message);
        $jsonData = array('success' => false, 'message' => $message);
        $json = json_encode($jsonData, true);
        echo $json;
        exit;
    }

    /**
     * 输出成功JSON信息
     * @param type $data
     */
    protected function successJSON($data = NULL, $msg = "success") {
        $jsonData = array('success' => true, 'data' => $data, 'message' => $msg);
        $json = json_encode($jsonData, 1);
        echo $json;
        exit;
    }

    /**
     * 获取当前页码
     * @return type
     */
    protected function getPageIndex() {
        $pageIndex = $this->_get('page');
        if (empty($pageIndex))
            $pageIndex = -1;
        return $pageIndex;
    }

    /**
     * 获取每页显示数量
     * @return type
     */
    protected function getPageSize() {
        $pageSize = $this->_get('rows');
        if (empty($pageSize))
            $pageSize = -1;
        if ($pageSize > 50)
            $pageSize = 50;
        return $pageSize;
    }

    /**
     * 保存base64 图片
     * @param type $base64
     * @param type $user_id
     * @return boolean|string
     */
    protected function base_img_upload($base64, $user_id, $savePath) {
        // 获取表单上传文件 例如上传了001.jpg
        if (empty($base64)) return false;
        $_message = array(
            'success' => false,
            'message' => '',
        );
        $rootPath = UPLOADFOLDER;
        $uploadFolder = substr($rootPath, 1);
        $uploadPath = $uploadFolder . $savePath;
        $path = $_SERVER['DOCUMENT_ROOT'] . $uploadPath;
        $file_name = time() . getMD5Name(3, $user_id);
        $new_file_name = time() . getMD5Name(6, $user_id);
        if (!is_dir($path)) mkdir($path, 0777, true);
        if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64, $result)) {
            $ext = array('jpg', 'png', 'jpeg');
            $type = $result[2];
            if (!in_array($type, $ext)) {
                $_message['message'] = lang('API_IMG_FORMAT');
                return $_message;
            }
            $pic_path = $path . $file_name . "." . $type;
            $new_pic_path = $path . $new_file_name . "." . $type;
            $file_size = file_put_contents($pic_path, base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $base64)));
            if (!$pic_path || $file_size > 10 * 1024 * 1024&&getimagesize($pic_path)) {
                unlink($pic_path);
                $_message['message'] = lang('API_IMG_SAVE');
                return $_message;
            }
            if (in_array($type, ['jpg', 'jpeg'])) {
                $img = imagecreatefromjpeg($pic_path);
                imagejpeg($img,$pic_path,100);
            }else {
                $img = imagecreatefrompng($pic_path);
                imagepng($img,$pic_path,9);
            }
            imagedestroy($img);
            if(!rename( $pic_path,$new_pic_path)) {
                $_message['message'] = lang('API_IMG_CODE');
                return $_message;
            }
        } else {
            $_message['message'] = lang('API_IMG_CODE');
            return $_message;
        }
        $_message['success'] = true;
        $_message['message'] = lang('API_IMG_UPLOAD');
        $_message['path'] = $uploadPath . $new_file_name . '.' . $type;
        return $_message;
    }
    
    private function addImgMark($image_path){
        $image = \think\Image::open($image_path);
        $image->water('watermark.png')->save($image_path);
    }
   /**
     * 获取手机验证码
     */
    public function getVerify() {
        $country_code = $this->_post('country_code', true, 'int');
        if(!$country_code) $country_code = 86;
        // if($country_code == '00886' || $country_code == '00852'){
        //     $country_code = '86';
        // }
        $country_code = 86;
        $phone = $this->_post('phone');
        $time = 120;
        $type = $this->getParamVal('type',true,'int');
        if (empty($type))
            $type = 1; //注册验证码
        if ($type == 2 || $type == 3) {
            //找回密码
            $memberM = new \addons\member\model\MemberAccountModel();
            $ret = $memberM->hasRegsterPhone($phone);
            if ($ret <= 0) {
                return $this->failJSON(lang('API_PHONE_NONE'));
            }
        }
        $m = new \addons\member\model\VericodeModel();
        $unpass_code = $m->hasUnpassCode($phone, $type, $country_code);
        if (!empty($unpass_code)) {
            return $this->failJSON(lang('API_CODE_EXISTS'));
        }
        //判断同一手机今天获取手机次数
        $smsDayCount = $m->getTodaySmsCount($phone);
        if ($smsDayCount > 5) return $this->failJSON(lang('API_CODE_LIMIT'));
        try {
            //发送验证码$country_code .
            $res = \addons\member\utils\ChSms::send($phone);
            // $res['success'] = true;
            // $res['message'] = '短信发送成功:1111';
            // $res['code'] = '1111';
            // if (!$res['success']) {
            //     return $this->failJSON($res['message']);
            // }
            //保存验证码
            $pass_time = date('Y-m-d H:i:s', strtotime("+" . $time . " seconds"));
            $data['country_code'] = $country_code;
            $data['phone'] = $phone;
            $data['code'] = $res['code'];
            $data['type'] = $type;
            $data['pass_time'] = $pass_time; //过期时间
            $result = $m->add($data);
            if (empty($result)) {
                return $this->failJSON(lang('API_CODE_FAIL')); //写入数据库失败
            }
            unset($res['code']);
            return $this->successJSON($res['message']);
        } catch (\Exception $ex) {
            return $this->failJSON($ex->getMessage());
        }
    }
    /**
     * 输出错误JSON信息。
     * @param type $message
     */
    protected function failLoginJSON($message,$status=404) {
        $jsonData = array('status' => $status, 'message' => $message);        
        exit(json_encode($jsonData, true));
    }

    /**
     * 模拟GET表单提交
     * @access protected
     * @param string $url 链接
     * @since 1.0
     * @return string
     */
    protected function _curlGet($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $info = curl_exec($ch);
        if (curl_errno($ch)) {
            echo 'Error' . curl_error($ch);
        }
        curl_close($ch);
        return $info;
    }



    protected function cacheLock($lockKey,$locktime = 2){
        $redis = (\think\Cache::connect(\think\Config::get('global_cache')))->getHandler();
        $randValue = rand(10000, 99999);    //lock
        $lock = $redis->set($lockKey, $randValue, ['NX', 'EX'=>$locktime]);
        if(!$lock) {
            // exit();
            return $this->failJSON(600);
        }
        $script = '
            if redis.call("get",KEYS[1]) == ARGV[1] then
                return redis.call("del",KEYS[1])
            else
                return 0
            end
        ';
        return ['redis'=>$redis,'script'=>$script,'data'=>[$lockKey, $randValue]];
    }

}
